﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;

namespace PefStudio.Windows
{
    public partial class AbstractDockDocument : AbstractFloatDocument
    {
        public AbstractDockDocument()
        {
            InitializeComponent();
        }

        public event EventHandler ActivePadChanged;
        public event EventHandler ActiveDocumentChanged;

        private readonly List<AbstractDocument> _documents = new List<AbstractDocument>();
        public List<AbstractDocument> Documents
        {
            get { return _documents; }
        }

        private readonly List<AbstractPad> _pads = new List<AbstractPad>();
        public List<AbstractPad> Pads
        {
            get { return _pads; }
        }

        private AbstractPad _activePad;
        public AbstractPad ActivePad
        {
            get
            {
                return _activePad;
            }
            set
            {
                if (_activePad != value)
                {
                    _activePad = value;

                    if (ActivePadChanged != null)
                        ActivePadChanged.Invoke(this, new EventArgs());
                }
            }
        }

        public AbstractPad FindPad(Type type)
        {
            return Pads.FirstOrDefault(pad => pad.GetType() == type);
        }

        public void ShowPad(AbstractPad doc)
        {
            foreach (var pad in Pads)
            {
                if (pad.GetType() == doc.GetType())
                {
                    pad.Activate();
                    return;
                }
            }

            Pads.Add(doc);

            doc.DockAreas = DockAreas.Float | DockAreas.DockLeft | DockAreas.DockRight | DockAreas.DockTop | DockAreas.DockBottom;
            doc.Show(dockPanel);

            doc.FormClosed += new FormClosedEventHandler(AbstractPad_FormClosed);
        }

        public void ShowPad(AbstractPad doc, DockState dockState)
        {
            ShowPad(doc);
            doc.DockState = dockState;
        }

        public void ShowPad(AbstractPad doc, DockPane pane)
        {
            ShowPad(doc);
            doc.Pane = pane;
        }

        void AbstractPad_FormClosed(object sender, FormClosedEventArgs e)
        {
            var doc = sender as AbstractPad;
            Pads.Remove(doc);
        }

        protected virtual void AddDocument(AbstractDocument doc)
        {
            Documents.Add(doc);
            doc.ParentDockDocument = this;

            doc.FormClosed += new FormClosedEventHandler(AbstractDocument_FormClosed);
            doc.TitleChanged += new EventHandler(AbstractDocument_TitleChanged);

            if (ActiveDocumentChanged != null)
                ActiveDocumentChanged.Invoke(this, new EventArgs());

            if (doc is AbstractDockDocument)
            {
                var dockDoc = doc as AbstractDockDocument;
                dockDoc.ActiveDocumentChanged += new EventHandler(dockDoc_ActiveDocumentChanged);
            }
        }

        void dockDoc_ActiveDocumentChanged(object sender, EventArgs e)
        {
            if (ActiveDocumentChanged != null)
                ActiveDocumentChanged.Invoke(this, new EventArgs());
        }

        void AbstractDocument_TitleChanged(object sender, EventArgs e)
        {
            var doc = sender as AbstractDocument;
            if (doc != null) this.Title = doc.Title;
        }

        public void ShowDocument(AbstractDocument doc)
        {
            AddDocument(doc);

            doc.DockAreas = DockAreas.Document;
            doc.Show(dockPanel);
        }

        public void ShowFloatDocument(AbstractFloatDocument doc)
        {
            AddDocument(doc);

            doc.DockAreas = DockAreas.Document | DockAreas.Float;
            doc.Show(dockPanel);
        }

        public void ShowFloatDocument(AbstractFloatDocument doc, bool showFloat)
        {
            if (showFloat == false)
            {
                ShowFloatDocument(doc);
                return;
            }

            AddDocument(doc);

            doc.DockAreas = DockAreas.Document | DockAreas.Float;
            doc.Show(dockPanel, DockState.Float);
        }

        public void ShowFloatDocument(AbstractFloatDocument doc, int width, int height)
        {
            AddDocument(doc);

            doc.DockAreas = DockAreas.Document | DockAreas.Float;
            doc.Show(dockPanel, DockState.Float);
            doc.FloatPane.FloatWindow.Size = new Size(width, height);
        }

        void AbstractDocument_FormClosed(object sender, FormClosedEventArgs e)
        {
            var doc = sender as AbstractDocument;
            Documents.Remove(doc);

            if (Documents.Count == 0)
                ActiveDocument = null;

            if (ActiveDocumentChanged != null)
                ActiveDocumentChanged.Invoke(this, new EventArgs());
        }

        private AbstractDocument _activeDocument;
        public AbstractDocument ActiveDocument
        {
            get
            {
                return _activeDocument;
            }
            set
            {
                if (value != null)
                    value.RefreshActiveStatus();
                if (_activeDocument != value)
                {
                    _activeDocument = value;

                    if (ActiveDocumentChanged != null)
                        ActiveDocumentChanged.Invoke(this, new EventArgs());
                }
                if (ParentDockDocument != null && ParentDockDocument.ActiveDocument != this)
                {
                    Activate();
                    if (value != null)
                    {
                        value.Focus();
                        value.Activate();
                    }
                }
            }
        }

        private void dockPanel_ActiveDocumentChanged(object sender, EventArgs e)
        {
            if (dockPanel.ActiveDocument == null)
                return;
        }

        private void dockPanel_ActiveContentChanged(object sender, EventArgs e)
        {
            if (dockPanel.ActiveContent == null)
                return;

            if (dockPanel.ActiveContent is AbstractPad)
            {
                ActivePad = dockPanel.ActiveContent as AbstractPad;
                return;
            }

            if (dockPanel.ActiveContent is AbstractDocument)
                ActiveDocument = dockPanel.ActiveContent as AbstractDocument;
        }
    }
}
